﻿using System.Text;

using ApproveFlowEngine.Split;

namespace ApproveFlowEngine.EntityFrameworkCore
{
    public class TableTailHelper
    {
        #region Private Fields

        private static readonly AsyncLocal<Dictionary<Type, string>> _dbContextMap = new AsyncLocal<Dictionary<Type, string>>() { Value = new Dictionary<Type, string>() };
        private static AsyncLocal<bool> _isCreatingTable = new AsyncLocal<bool>() { Value = false };

        #endregion Private Fields



        #region Public Methods

        public static void Clear()
        {
            CheckValue();
            _dbContextMap.Value.Clear();
        }

        public static void CreatingTable(bool isCreating)
        {
            _isCreatingTable.Value = isCreating;
        }

        public static string GetKey()
        {
            if (_isCreatingTable.Value)
            {
                return "CreatingTable";
            }
            CheckValue();
            var sb = new StringBuilder();
            foreach (var item in _dbContextMap.Value)
            {
                sb.Append($"[{item.Key.Name}_{item.Value}]");
            }
            return sb.ToString();
        }

        public static string GetTail<TSplitEntity>() where TSplitEntity : ISplitTable
        {
            CheckValue();
            if (_dbContextMap.Value.TryGetValue(typeof(TSplitEntity), out var tail))
            {
                return tail;
            }
            else
            {
                return string.Empty;
            }
        }

        public static Dictionary<Type, string> GetTail()
        {
            CheckValue();
            return _dbContextMap.Value;
        }

        public static bool SetTail<TSplitEntity>(string tail) where TSplitEntity : ISplitTable
        {
            return AddOrUpdate(typeof(TSplitEntity), tail);
        }

        public static bool SetTail(Type type, string tail)
        {
            return AddOrUpdate(type, tail);
        }

        #endregion Public Methods



        #region Private Methods

        private static bool AddOrUpdate(Type type, string tail)
        {
            CheckValue();
            if (type.IsAssignableTo<ISplitTable>())
            {
                if (_dbContextMap.Value.ContainsKey(type))
                {
                    _dbContextMap.Value[type] = tail;
                    return true;
                }
                else
                {
                    return _dbContextMap.Value.TryAdd(type, tail);
                }
            }
            return false;
        }

        private static void CheckValue()
        {
            if (_dbContextMap.Value is null)
            {
                _dbContextMap.Value = new Dictionary<Type, string>();
            }
        }

        #endregion Private Methods
    }
}